Vue

您所在的位置:网站首页 vue store 刷新 Vue

Vue

#Vue| 来源: 网络整理| 查看: 265

[TOC]

干嘛的?

用于解决组件之间数据共享,数据的集中处理,是一种状态管理的设计模式。

什么是vuex ?单项数据流 Vuex 是一个专为 Vue.js 应用程序开发的状态管理器,采用 集中式存储 管理所有组件的状态。

vuex的原理其实非常简单,它为什么能实现所有的组件共享同一份数据?

因为vuex生成了一个store实例,并且把这个实例挂在了所有的组件上,所有的组件引用的都是同一个store实例。store实例上有数据,有方法,方法改变的都是store实例上的数据。由于其他组件引用的是同样的实例,所以一个组件改变了store上的数据,导致另一个组件上的数据也会改变,就像是一个对象的引用。

基本使用#安装 yarn add vuex #引入 一般我们会在src根目录下创建一个store的文件夹, #下面写index.js来实现相关的存储方法(组件共用数据) import Vuex from 'vuex' import Vue from 'vue' Vue.use(Vuex)

vuex的组成部分(应用结构)

vuex的工作流程1.通过this.$store.dispatch()向vuex中的actions派发一个事件同时传递一个参数 methods:{ handleClick(city){ /* this.$store.dispatch 向vuex派发一个事件,同时传递一个参数 */ this.$store.dispatch("changeCity",city) } } 2.vuex-actions中接收dispatch派发过来的事件和参数 export default new Vuex.Store({ ... actions: { changeCity(ctx,city){ /* ctx表示上下文 this.$store city是自定义事件传递过来的参数 */ 3.在actions中使用commit方法向mutations提交一个事件,同时传递一个参数 ctx.commit("toggleCity",city) } } }) 4.在mutations中接收commit方法提交过来的事件,同时改变state中的状态 export default new Vuex.Store({ state: { city:"武汉" }, mutations: { toggleCity(state,city){ state.city = city; } } })

数据持久化 =>设置缓存机制function getCity(){ let defaultCity = "天门"; if(localStorage.getItem("city")){ defaultCity = localStorage.getItem("city") } return defaultCity; } export default new Vuex.Store({ state: { city:getCity() }, mutations: { changeCity(state,city){ state.city = city; } }, actions: { changeCity(ctx,city){ ctx.commit("changeCity",city) //1.设置缓存 localStorage.setItem("city",city) } } })

State

State负责存储整个应用的状态数据,一般需要在使用的时候在跟节点注入store对象,后期就可以使用this.$store.state直接获取状态。一般是在main.js文件中引入store的文件,从而使用。(vue spa应用中)

//store为实例化生成的 import store from './store' new Vue({ el: '#app', store, render: h => h(App) })

这个store可以理解为一个容器,包含着应用中的state等。实例化生成store的过程是:

const mutations = {...}; const actions = {...}; const state = {...}; Vuex.Store({ state, actions, mutation });

后续在组件中使用的过程中,如果想要获取对应的状态你就可以直接使用this.$store.state获取,当然,也可以利用vuex提供的mapState辅助函数将state映射到计算属性中去,如

mapStatestate: { count:0, city:"武汉", name:"港啊", age:20, sex:"男" },

{{city}} {{age}} import {mapState} from 'vuex'; export default { name: 'home', computed:{ ...mapState(['city','name','age','sex']) } }

映射

Mutations

Mutations的中文意思是“变化”,利用它可以更改状态,本质就是用来处理数据的函数,其接收唯一参数值state。store.commit(mutationName)是用来触发一个mutation的方法。需要记住的是,定义的mutation必须是同步函数,否则devtool中的数据将可能出现问题,使状态改变变得难以跟踪。| 直接派发一个事件给mutations

export default { methods: { handleClick() { this.$store.commit('changeCity') } } } mutations:{ changeCity(state){ state.city="成都" } }

或者使用辅助函数mapMutations直接将触发函数映射到methods上,这样就能在元素事件绑定上直接使用了。如:

mapMutations {{this.$store.state.count}} 增加 减少 import {mapMutations} from 'vuex'; export default { name: 'home', methods:{ ...mapMutations(['myIncrease','myDecrease']) } } mutations: { myIncrease(state){ state.count+=1 }, myDecrease(state){ state.count-=1 } },

映射

Actions

Actions也可以用于改变状态,不过是通过触发mutation实现的,重要的是可以包含异步操作。其辅助函数是mapActions与mapMutations类似,也是绑定在组件的methods上的。如果选择直接触发的话,使用this.$store.dispatch(actionName)方法。action内部支持异步方法,这是很重要的一点区别。

mapActionsexport default new Vuex.Store({ state: { count:0 }, /* 异步操作,处理一些复杂的业务逻辑 */ actions: { increase(ctx){ ctx.commit("myIncrease") }, decrease(ctx){ ctx.commit("myDecrease") } }, /* 简单的更改状态(state)的逻辑*/ mutations: { myIncrease(state){ state.count+=1; }, myDecrease(state){ state.count-=1; } }, }) 映射 ```css {{this.$store.state.count}} ``` ## Getters 有些状态需要做二次处理,就可以使用getters。通过this.$store.getters.valueName对派生出来的状态进行访问。或者直接使用辅助函数mapGetters将其映射到本地计算属性中去。这个属性相当于vuex的计算属性。 ```css /* 对state中的数据进行再次处理 */ getters:{ myCount(state){ return "当前的数量:"+state.count; } } ``` ### mapGetters ```css //mapGetters 将 store 中的 getter 映射到局部计算属性 import {mapGetters} from 'vuex'; export default { name: 'home', computed:{ ...mapGetters(['myCount']) } } ``` ## Plugins 插件就是一个钩子函数,在初始化store的时候引入即可。比较常用的是内置的logger插件,用于作为调试使用。 ``` import createLogger from 'vuex/dist/logger' const store = Vuex.Store({ ... plugins: [createLogger()] }) ``` ## modules 随着项目的复杂性增加,我们共享的状态越来越多,这时候我们就需要把我们状态的各种操作进行一个分组,分组后再进行按组编写。作用:当store对象非常复杂的时候,我们可以根据将其拆分成不同的模块 ### 1. 新建modules文件夹,拆分module ![module.png](https://cdn.nlark.com/yuque/0/2019/png/402644/1574323726476-dd6e883b-6aff-479c-93cc-452955ffab4d.png#align=left&display=inline&height=380&name=module.png&originHeight=380&originWidth=563&size=22125&status=done&style=none&width=563) ```javascript //user.js const user = { state: { name:"程超" }, mutations:{}, actions: { }, getters: { } } export default user; ``` ```javascript //info.js const info = { state: { tips:12, news:15 }, mutations: { add(state){ state.tips++; }, reduce(state){ state.tips--; } }, actions: { }, getters: { } } export default info; ``` ```javascript //index.js export default new Vuex.Store({ modules:{ user, info } }) ``` ### 2. 使用数据 ```javascript 首页 {{tips}} {{news}} {{name}} ``` ## 注意事项 ### 更新数据 正如文档中所说,我们应该将所有的数据修改都定义在mutations中,这才是科学正确的做法。 ### state更改报错 Error in v-on handler: "Error: [vuex] use store.replaceState()to explicit replace store state."Error: [vuex] use store.replaceState() toexplicit replace store state. 报错如上,是因为修改state的时候,写成了this.state = data ,正确的写法应该是 this.state.xxx =data ; ### vuex与持久存储localStorage的关系 **场景** :发现部分开发在引入持久存储之后,mutation的时候没有改变state,而是直接修改的localStorage,这样会导致没有页面刷新时,拿到的state都是不对的。因为state不会实时监听localStorage的更改。**解决方案** :1 更改state的时候,除了更改localStorage,也要更改state,而且更改state才是必须要做的,而更改localStorage只是为了解决刷新页面后数据丢失的问题。(推荐方式,毕竟使用vuex的全套才是正宗)2 如果你觉得上面的方案每次都写很麻烦,也可以尝试增加locastorage的监听机制,当发生变化的时候,寻找更改对应的state. ### 拓展符写法 在mapState,mapActions,mapMutations使用的时候,为了不影响正常方法的使用,我们可以使用对象以及数组的拓展方法进行拓展。 ``` methods:{ ...mapMutations([ 'add','reduce' ]), ...mapActions(['addAction','reduceAction']) }, // 获取state属性,你也可以采用这种写法 import {mapState} from 'vuex'; computed:mapState({ count:state=>state.count }) ``` ### 单页中直接定义使用(特别说明) ``` // 如果在模块化构建系统中,请确保在开头调用了 Vue.use(Vuex) const store = new Vuex.Store({ state: { count: 0 }, mutations: { increment (state) { state.count++ } } }) //使用的时候 如果想改变数值,必须用事件触发,不是直接改变。 store.commit('increment') console.log(store.state.count) // -> 1 ``` ## 个人理解 自我实践下来,如果要用好vuex,需要掌握以下的几点。1 组件数据共享,跨页面数据共享,可以统一管理数据的存储,操作,分发。比如用户数据,比如固定的某些数据是固定某些api获取的且不止用于一个组件或者一个场景。2 不要形式主义,每个页面都用vuex;每个模块都写getters,actions,常量方法,当你的工程量、数据量达到使用某技术场景的时候,采用某方案会觉得恰如其分3 处理基于数据的业务逻辑,一般是跨页面跨组件的,比如购买流程对用户余额,购物车,订单的联动影响4 vuex核心的index做一些模块公用的存储工具,可以配置一些需要的插件或者工具类5 拓展:数据通讯不止vuex,简单的也可以用event bus,甚至页面内的已经能符合你的需求了6 actions,支持异步是指更加建议在action中写异步,写复杂的逻辑,而所有的更改state建议写在mutations ## 使用vuex的核心概念 每一个 Vuex 应用的核心就是 store(仓库)。“store”基本上就是一个容器,它包含着你的应用中大部分的状态 (state)。 ### vuex的核心概念和核心概念图: 1、state - Vuex store实例的根状态对象,用于定义共享的状态变量。2、Action -动作,向store发出调用通知,执行本地或者远端的某一个操作(可以理解为store的methods)3、Mutations -修改器,它只用于修改state中定义的状态变量。4、getter -读取器,外部程序通过它获取变量的具体值,或者在取值前做一些计算(可以认为是store的计算属性) ### Vuex的应用场景: Vuex主要用于:1、多层嵌套的组件之间进行状态传递2、兄弟组件间进行状态传递时(当然也可以使用中央事件总线BUS)3、多组件共享状态时

更为具体的场景:组件之间的状态、音乐播放、登录状态、加入购物车...![288a0dc913bab3fe765baf18fb4bac27_701x551.png](https://cdn.nlark.com/yuque/0/2020/png/402644/1583220449909-28a05844-6698-470a-96fa-ac240fe36d0f.png#align=left&display=inline&height=551&name=288a0dc913bab3fe765baf18fb4bac27_701x551.png&originHeight=551&originWidth=701&size=8091&status=done&style=none&width=701) ### 代码: ```javascript //vuex的使用 #1.安装vuex npm i vuex -S #2.main.js import Vue from 'vue' import Vuex from 'vuex' // 注册vuex到vue中 Vue.use(Vuex) // new Vuex.Store()实例,得到一个数据仓储对象 // 可以在组件中通过this.$store.state.xx 来访问store中的数据 var store = new Vuex.Store({ //state相当于组件中的data state: { count: 0 }, //如果要修改store中state的值,需要调用 mutations提供的方法,可以通过this.$store.commit('方法名')来调用 mutations: { increment(state) { state.count++ }, //mutations函数参数列表中最多支持两个参数,其中参数1是state; 参数2是通过commit提交过来的参数; subtract(state, obj) { console.log(obj) state.count -= obj.step; } }, getters: { //这里的getters只负责对外提供数据,不负责修改数据,如果想要修改 state 中的数据需要在mutations中修改 optCount: function (state) { return '当前最新的count值是:' + state.count } } }) // 总结: // 1. state中的数据,不能直接修改,如果想要修改,必须通过 mutations // 2. 如果组件想要直接 从 state 上获取数据: 需要 this.$store.state.*** // 3. 如果组件想要修改数据,必须使用 mutations 提供的方法,需要通过 this.$store.commit('方法的名称', 唯一的一个参数) // 4. store中state上的数据在对外提供的时候建议做一层包装,推荐使用 getters。调用的时候则用this.$store.getters.*** import App from './App.vue' const vm = new Vue({ el: '#app', render: c => c(App), //将vuex创建的store挂载到VM实例上,只要挂载到了 vm 上,任何组件都能使用store来存取数据 store }) #3.index.html

#4.App.vue 这是 App 组件 5.components/amount.vue {{ $store.getters.optCount }} 6.components/counter.vue

```



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3